﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Reactive.Concurrency;
using System.Reflection;
using System.Windows.Input;
using AlanAamy.Net.TemperatureConverter.Infrastructure.Constants;
using AlanAamy.Net.TemperatureConverter.Infrastructure.Frameworks.MVVM;
using AlanAamy.Net.TemperatureConverter.Models;
using AlanAamy.Net.TemperatureConverter.Services;
using log4net;

namespace AlanAamy.Net.TemperatureConverter.Views
{
    [ExportViewModel("MainPage", true)]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class MainPageViewModel : ViewModel
    {
        private static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private readonly ISequenceObserverController _controllerService;
        private readonly IRightSequenceObserverModel _rightSequenceObserverModel;
        private readonly ILeftSequenceObserverModel _leftSequenceObserverModel;
        private readonly IMemoryLogAppenderService _logAppenderService;
        private readonly ObservableCollection<string> _logMessages = new ObservableCollection<string>();
            
        [ImportingConstructor]
        public MainPageViewModel(IMemoryLogAppenderService logAppenderService,ISequenceObserverController controllerService, 
            IRightSequenceObserverModel rightSequenceObserverModel, ILeftSequenceObserverModel leftSequenceObserverModel)
        {
            _logAppenderService = logAppenderService;
            _logAppenderService.LogAppend += (o, e) => { _logMessages.Add(string.Format("{0} : {1}",e.LoggingEvent.Level.DisplayName,e.LoggingEvent.MessageObject.ToString())); };
            Log.Debug("Application is starting");
            _controllerService = controllerService;
            _rightSequenceObserverModel = rightSequenceObserverModel;
            _leftSequenceObserverModel = leftSequenceObserverModel;
            _rightSequenceObserverModel.ValueChanged += (o, e) => { RaisePropertyChanged("RightSequence"); };
            _rightSequenceObserverModel.UnitChanged  += (o, e) => { RaisePropertyChanged("CurrentRightTemperatureUnit"); };
            _leftSequenceObserverModel.ValueChanged  += (o, e) => { RaisePropertyChanged("LeftSequence"); };
            _rightSequenceObserverModel.UnitChanged  += (o, e) => { RaisePropertyChanged("CurrentLeftTemperatureUnit"); };
        }

        public ICommand ObserveInputSequence
        {
            get
            {
                return new RelayCommand<TemperatureUnit>(d =>
                {
                    Log.Debug("ObserveInputSequence " + ( d == CurrentLeftTemperatureUnit ? UnitConversionMode.LeftToRight : UnitConversionMode.RightToLeft));
                    _controllerService.RewireSequenceObservers(d == CurrentLeftTemperatureUnit ? UnitConversionMode.LeftToRight : 
                        UnitConversionMode.RightToLeft, d, Scheduler.Default, DispatcherScheduler.Current);
                });
            }
        }

        /// <summary>
        /// User has now changed the unit of conversion
        /// Any changes now are merely to be on the existing state and not on 
        /// any new sequence input from user.
        /// 1. UnWire the Sequence Observers. 
        /// 2. Toggle the Left and Right Conversion Unit , convert RightSequence Value
        /// </summary>
        public TemperatureUnit CurrentLeftTemperatureUnit
        {
            get { return _leftSequenceObserverModel.Unit; }
            set
            {
                if (_leftSequenceObserverModel.Unit == value) return;
                _controllerService.ToggleUnWireSequenceObservers();
                Log.Debug("LeftTemperatureUnit Changed to " + value);
            }
        }
        /// <summary>
        /// User has now changed the unit of conversion
        /// Any changes now are merely to be on the existing state and not on 
        /// any new sequence input from user.
        /// 1. UnWire the Sequence Observers. 
        /// 2. Toggle the Left and Right Conversion Unit , convert RightSequence Value
        /// </summary>
        public TemperatureUnit CurrentRightTemperatureUnit
        {
            get { return _rightSequenceObserverModel.Unit; }
            set
            {
                if (_rightSequenceObserverModel.Unit == value) return;
                _controllerService.ToggleUnWireSequenceObservers();
                Log.Debug("RightTemperatureUnit Changed to " + value);
            }
        }

        public Decimal LeftSequence
        {
            get { return _leftSequenceObserverModel != null ? _leftSequenceObserverModel.Value : 0; }
            set
            {
                if (value == Decimal.MaxValue || _leftSequenceObserverModel.Value == value) return;
                _leftSequenceObserverModel.Value = value;
            }

        }

        public Decimal RightSequence
        {
            get { return _rightSequenceObserverModel != null ? _rightSequenceObserverModel.Value : 0; }
            set
            {
                if (value == Decimal.MaxValue || _rightSequenceObserverModel.Value == value) return;
                _rightSequenceObserverModel.Value = value;
            }

        }

        public ObservableCollection<string> LogMessages
        {
            get { return _logMessages; }
        }

    }

    public class MainPageViewModelDesign : ViewModel
    {
        #region Properties
 
        #endregion

    }
}
